﻿using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using CalcSharp.Core.Containers;
using System;

namespace CalcSharp.Core
{
    public class RawDriver
    {
        private int width, height;
        private int bytesperpixel;
        private Stream Input;

        public RawDriver(Stream src, int w, int h, int bytes)
        {
            if (bytes != 1 && bytes != 2 && bytes != 3 && bytes != 4) throw new CSException("This driver only supports 1-4 bytes/pixel mode");
            this.Input = src;
            this.width = w;
            this.height = h;
            this.bytesperpixel = bytes;
        }

        public Bitmap ReadBitmap()
        {
            byte[] tmp;
            Bitmap ret = new Bitmap((int)this.width, (int)this.height, PixelFormat.Format24bppRgb);
            BinaryReader br = new BinaryReader(this.Input);
            Int24 cnv = new Int24();
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    tmp = br.ReadBytes(bytesperpixel);
                    Array.Reverse(tmp);
                    cnv.FromByteArray(tmp);
                    ret.SetPixel(j, i, cnv.ToColor());
                }
            }
            br.Close();
            return ret;
        }

        public AMatrix ReadMatrix(out long mem, MtrxStorageType t)
        {
            AMatrix ret;
            switch (t)
            {
                case MtrxStorageType.tdouble:
                    ret = new DoubleMatrix(this.height, this.width);
                    break;
                case MtrxStorageType.tfloat:
                    ret = new FloatMatrix(this.height, this.width);
                    break;
                case MtrxStorageType.tint24:
                    ret = new Int24Matrix(this.height, this.width);
                    break;
                default:
                    ret = new FloatMatrix(this.height, this.width);
                    break;
            }

            BinaryReader br = new BinaryReader(this.Input);
            byte[] tmp;
            Int24 cnv = new Int24();

            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    tmp = br.ReadBytes(bytesperpixel);
                    Array.Reverse(tmp);
                    cnv.FromByteArray(tmp);
                    ret[i, j] = cnv.ToInt32();
                }
            }
            br.Close();
            mem = ret.Columns * ret.Rows * (int)t;
            return ret;
        }

        public void WriteBitmap(Bitmap bmp)
        {
            Int24 color = new Int24();
            BinaryWriter bw = new BinaryWriter(Input);
            for (int i = 0; i < bmp.Height; i++)
            {
                for (int j = 0; j < bmp.Width; j++)
                {
                    color.FromColor(bmp.GetPixel(j, i));
                    bw.Write(color.ToByteArray());
                }
            }
            bw.Close();
        }

        public void WriteMatrix(AMatrix mtrx)
        {
            Int24 color = new Int24();
            BinaryWriter bw = new BinaryWriter(Input);
            for (int i = 0; i < mtrx.Rows; i++)
            {
                for (int j = 0; j < mtrx.Columns; j++)
                {
                    color.FromInt32((int)mtrx[i, j]);
                    bw.Write(color.ToByteArray());
                }
            }
            bw.Close();
        }
    }
}
